#ifndef __LOOPTHREAD_HPP__
#define __LOOPTHREAD_HPP__

/* LoopThread模块：
    为了连接的操作是线程安全的，但又为了提高效率，就让对同一个连接的所有操作都在同一个线程中执行（而非使用可能的大量锁）。
    对连接的操作是在Loop中进行，而Loop又是在Thread中被实例化（这样是线程安全的），然后在所属的Thread中“运行”起来。这就实现了
    一个Loop对应一个Thread。

    不能先实例化EventLoop，再创建线程，然后将线程id分配给EventLoop，这样的操作本身就是非线程安全的！！！
 */

class LoopThread
{
private:
    /* 防止Thread创建之后但对应的Loop对象未被实例化之前就被获取 */
    std::mutex _mutex;
    std::condition_variable _cond;

    EventLoop* _eventloop;// 关联的loop的句柄
    std::thread _thread;// eventloop对应的线程
private:
    /* 线程入口函数——在这里实例化EventLoop */
    void ThreadEntry()
    {
        // 1. 实例化eventloop
        EventLoop eventloop;// 生命周期随当前（创建出的）线程
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _eventloop = &eventloop;
            _cond.notify_all();// 唤醒_cond上可能存在的等待获取Loop的线程
        }
        // 2. 启动事件循环
        eventloop.Start();
    }
public:
    /**
     * @brief Construct a new Loop Thread object
     *  创建线程
     * 
     */
    LoopThread(): _eventloop(nullptr), _thread(std::thread(&LoopThread::ThreadEntry, this))
    {}
    /**
     * @brief Destroy the Loop Thread object
     *  回收线程资源
     * 
     */
    ~LoopThread()
    {
        if(_thread.joinable()) _thread.join();
    }

    /**
     * @brief 获取EventLoop对象的句柄
     * 
     * @return EventLoop* EventLoop对象的操作句柄
     */
    EventLoop* GetLoop()
    {
        // return _eventloop;
        EventLoop* loop = nullptr;
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _cond.wait(lock, [&](){ return _eventloop != nullptr; });// 保证获取到的loop是已经被实例化了
            loop = _eventloop;
        }
        return loop;
    }
};

class LoopThreadPool
{
private:
    size_t _thread_count;// 线程池中线程数量
    EventLoop* _baseloop;// 主Loop的句柄
    int _next_loop_idx;// 下一个要分配的loop的索引（简易负载均衡）

    std::vector<LoopThread*> _threads;// 从属线程集
    std::vector<EventLoop*> _loops;// 从属线程对应的loop集 为避免频繁调用GetLoop而引发的频繁加锁解锁，在创建线程时就取出\
        线程对应的loop记录起来，这样只需要一次加锁解锁操作
public:
    LoopThreadPool(EventLoop* eventloop): _thread_count(0), _baseloop(eventloop), _next_loop_idx(0)
    {}
    ~LoopThreadPool()
    {
        for(auto& th : _threads) delete th;
    }

    /* 获取线程池中线程个数 */
    size_t ThreadCount() const
    {
        return _thread_count;
    }

    /* 设置线程池中线程个数 */
    void SetThreadCount(size_t count)
    {
        _thread_count = count;
    }

    /* 实例化线程池，创建线程 */
    void CreateThreads()
    {
        if(_thread_count > 0)
        {
            _threads.resize(_thread_count);
            _loops.resize(_thread_count);
            // for(int i = 0; i < _threads.size(); ++i) _threads[i] = new LoopThread();
            for(int i = 0; i < _thread_count; ++i)
            {
                _threads[i] = new LoopThread();
                _loops[i] = _threads[i]->GetLoop();
            }
        }
    }

    /* 获取下一个要分配的Loop */
    EventLoop* NextLoop()
    {
        if(_thread_count == 0) return _baseloop;

        int pos = _next_loop_idx;
        _next_loop_idx = (_next_loop_idx + 1) % _thread_count;
        // return _threads[pos]->GetLoop();
        return _loops[pos];
    }
};

#endif